package com.sali.service.data_processor.chain;

import com.sali.commons.exception.ProcessChainHandlerInitException;
import com.sali.entity.ProcessDefinition;
import com.sali.entity.TransferObject;
import com.sali.service.data_processor.chain.handlers.TailChainHandler;
import com.sali.service.statistic.StatisticalIndicatorCollector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

// 责任链上下文
public class ProcessChainContext {

    public static final Logger log = LoggerFactory.getLogger(ProcessChainContext.class);

    // 处理链
    private List<IProcessChainHandler> chain;

    public ProcessChainContext() {
        this.chain = new ArrayList<>();
    }

    // 执行链路中各个单元的枚举值，各个执行单元链接顺序与其在枚举值在path中的顺序一致
    public void loadProcessChain(List<Integer> path, ProcessDefinition processDefinition) throws ProcessChainHandlerInitException {
        try {
            for (Integer pathCode : path) {
                //创建chain handler
                IProcessChainHandler chainHandler = ProcessChainHandlerFactory.createInstance(pathCode, processDefinition);
                this.chain.add(chainHandler);
            }
            this.chain.add(new TailChainHandler());
        } catch (Exception e) {
            log.error("[处理链{}] 初始化失败", path, e);
        }
    }

    // 执行责任链
    public void process(TransferObject obj) {
        try {
            for (IProcessChainHandler chainHandler : chain) {
                chainHandler.process(obj);
            }
            // 收集统计指标
            StatisticalIndicatorCollector.outputInc(obj);
        } catch (Exception e) {
            log.error("[处理链] 数据处理异常，输出异常数据到本地,数据：{}", obj.toString(), e);
            try {
                IProcessChainHandler tailHandler = this.chain.get(this.chain.size() - 1);
                tailHandler.process(obj);
            } catch (Exception ex) {
                log.error("[chain-context] 收尾处理异常: {}", e.getMessage(), e);
            } finally {
                //收集统计指标
                StatisticalIndicatorCollector.errorInc(obj);
            }
        }
    }

}
